1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*!
Parsers for simple symbolic tokens
*/
use super::*;

// Usage symbols

/// The symbol for an observing usage
pub const OBSERVED: &str = "-";
/// The symbol for a full usage
pub const USED: &str = "=";
/// The symbol for a purely borrowing usage
pub const UNUSED: &str = "*";
/// The symbol for a consuming usage
pub const CONSUMED: &str = "~";

/// Parse a usage glyph
pub fn usage(input: &str) -> IResult<&str, Usage> {
    alt((
        map(tag(OBSERVED), |_| Usage::OBSERVED),
        map(tag(USED), |_| Usage::USED),
        map(tag(UNUSED), |_| Usage::UNUSED),
        map(tag(CONSUMED), |_| Usage::CONSUMED),
    ))(input)
}

// Variance symbols

/// The symbol for bivariance
pub const BIVAR: &str = "*";
/// The symbol for covariance
pub const COVAR: &str = ">";
/// The symbol for contravariance
pub const CONTRAVAR: &str = "<";
/// The symbol for invariance
pub const INVAR: &str = "=";

/// Parse a variance glyph
pub fn variance(input: &str) -> IResult<&str, Variance> {
    alt((
        map(tag(BIVAR), |_| Variance::Bivariant),
        map(tag(COVAR), |_| Variance::Covariant),
        map(tag(CONTRAVAR), |_| Variance::Contravariant),
        map(tag(INVAR), |_| Variance::Invariant),
    ))(input)
}

// Relation symbols

/// The symbol for a "greater than or equal to" relation
pub const REL_GE: &str = ">=";
/// The symbol for a "greater than" relation
pub const REL_GT: &str = ">";
/// The symbol for a "less than or equal to" relation
pub const REL_LE: &str = "<=";
/// The symbol for a "less than" relation
pub const REL_LT: &str = "<";
/// The symbol for an equality relation
pub const REL_EQ: &str = "==";
/// The symbol for an inequality relation
pub const REL_NE: &str = "!=";
/// The symbol for the trivial relation
pub const REL_TV: &str = "*";
/// The symbol for a contradictory relation
pub const REL_CN: &str = "!";

/// Parse a relationship
///
/// # Examples
/// ```rust
/// # use isotope::parser::*;
/// # use isotope::value::{self, *};
/// use value::relationships::*;
/// assert_eq!(relationship(">=").unwrap(), ("", GE));
/// assert_eq!(relationship(">").unwrap(), ("", GT));
/// assert_eq!(relationship("<=").unwrap(), ("", LE));
/// assert_eq!(relationship("<").unwrap(), ("", LT));
/// assert_eq!(relationship("==").unwrap(), ("", EQ));
/// assert_eq!(relationship("!=").unwrap(), ("", NE));
/// assert_eq!(relationship("*").unwrap(), ("", TV));
/// assert_eq!(relationship("!").unwrap(), ("", CN));
/// ```
pub fn relationship(input: &str) -> IResult<&str, Relationship> {
    alt((
        map(tag(REL_GE), |_| Relationship::GE),
        map(tag(REL_GT), |_| Relationship::GT),
        map(tag(REL_LE), |_| Relationship::LE),
        map(tag(REL_LT), |_| Relationship::LT),
        map(tag(REL_EQ), |_| Relationship::EQ),
        map(tag(REL_NE), |_| Relationship::NE),
        map(tag(REL_CN), |_| Relationship::CN),
        map(tag(REL_TV), |_| Relationship::TV),
    ))(input)
}

/// Parse a dependency
/// 
/// # Examples
/// ```rust
/// # use isotope::parser::*;
/// # use isotope::value::*;
/// assert_eq!(dependency("=>"), Ok(("", Dependency::USED)));
/// ```
pub fn dependency(input: &str) -> IResult<&str, Dependency> {
    map(
        tuple((
            usage,
            variance,
            opt(delimited(
                preceded(tag("["), opt(ws)),
                relationship,
                preceded(opt(ws), tag("]")),
            )),
        )),
        |(usage, variance, relationship)| Dependency {
            relationship: relationship.unwrap_or(Relationship::GE).with_usage(usage),
            variance,
        },
    )(input)
}